package edu.ruc.cluster.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;

import edu.ruc.cluster.util.MyUserInfo;

/**
 * This class is used for running simple command(one or multiple commands) without interaction
 * Host(in format like deke@dlnode27) and password is needed in constructor
 * Method runCmd() is reloaded to adapt to parameter as String command or String[] commands
 * Remember: call close() once you finish operations on Object.
 * @author deke
 * 2012.11.27
 */
public class RunCommand {

	private DefaultLogHandler logHandler = null;

	private JSch jsch = null;
	private Session session = null;
	private Channel channel = null;
	private UserInfo userinfo = null;
	
	private OutputStream writor = null;
	private BufferedReader reader = null;
	
	private String user = null;
	
	public RunCommand(String host, String passwd){
		
		jsch = new JSch();
		userinfo = new MyUserInfo(passwd);
		
		logHandler = DefaultLogHandler.getInstance();
		
		String user = host.substring(0, host.indexOf('@'));
		host = host.substring(host.indexOf('@') + 1);
		this.user = user;
		
		try{
			System.out.println("user : " + user + " host: " + host);
			session = jsch.getSession(user, host, 22);
			session.setPassword(passwd);
			session.setUserInfo(userinfo);
			session.connect(2000);
			System.out.println("session.connect()");
			
			channel = (ChannelShell)session.openChannel("shell");
			channel.connect();
			System.out.println("channel.connect()");
			
			writor = channel.getOutputStream();
			reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));
			
		}catch(JSchException e){
			logHandler.error(this.getClass().getSimpleName() + " init():" + e.getClass().getSimpleName(), e);
		}catch(IOException e){
			logHandler.error(this.getClass().getSimpleName() + " init():" + e.getClass().getSimpleName(), e);
		}
		
	}
//	@SuppressWarnings("unused")
	public void close(){
		try{
			writor.close();
			reader.close();
//			System.out.println("reader.close()");
			channel.disconnect();
//			System.out.println("channel.disconnect()");
			session.disconnect();
//			System.out.println("session.disconnect()");
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	public String runCmd(String[] cmd){
		
		String result = null;
		try{
			for(int i = 0 ; i < cmd.length ; i ++){
				writor.write((cmd[i] + "\r\n").getBytes());
				writor.flush();
				
				char[] cbuf = new char[1024];				
				int ret = reader.read(cbuf);
				int count = 1;
				
				while(ret != -1){
					String info = new String(cbuf, 0, ret);
//					System.out.print(i + info);	
					result += info;
					if(info.contains("[" + user + "@")){						
						if(count == 0){
//							System.out.println(i + "break");
							break;
						}
						count --;
					}
					ret = reader.read(cbuf);
				}				
			}
		}catch(IOException e){
			logHandler.error(this.getClass().getSimpleName() + " runCmd():" + e.getClass().getSimpleName(), e);
		}
		return result;
	}
	public void runCmd(String cmd){
		
		try{
			writor.write((cmd + "\r\n").getBytes());		
			writor.flush();
			
			char[] cbuf = new char[1024];			
			int ret = reader.read(cbuf);
			int count = 1;
			while(ret != -1){
				String info = new String(cbuf, 0, ret);
				System.out.print("---"+info);
				if(info.contains("[" + user + "@")){
					if(count == 0)
						break;
					count --;
				}
				else if(info.contains("[sudo]")){
					writor.write("111111\n".getBytes());
					writor.flush();
				}
				ret = reader.read(cbuf);				
			}
		}catch(IOException e){
			logHandler.error(this.getClass().getSimpleName() + " runCmd():" + e.getClass().getSimpleName(), e);
		}
			
	}
	
	public static void main(String[] args){
		/*
		 * attention here: if use ip instread of host like deke@10.77.110.202, there's mistake
		 */
//		RunCommand rc = new RunCommand("deke@10.77.110.202", "111111");
//		String[] cmd = {
//				"ping -c 1 10.77.110.196", "ping -c 1 10.77.110.200", "ping -c 1 10.77.110.202"
//		};
		RunCommand rc2 = new RunCommand("deke@dlnode27", "111111");
//		String cmd3 = "sudo ls /etc";
		String[] cmd2 = {
				"ping -c 1 dlnode13", "ping -c 1 dlnode17", "ping -c 1 dlnode19"
		};
		rc2.runCmd(cmd2);
//		System.out.println(rc2.runCmd(cmd2));
		System.out.println("going to close()");
//		for(int i = 0 ; i < cmd.length ; i ++)
//			rc.runCmd(cmd[i]);
		rc2.close();
//		rc.close();
//		System.out.println("aaa");
	}
	
}
